#!/bin/sh
#
# Promote __pmFoo to pmFoo
# Demote pmFoo to __pmFoo
# ... or in general rename foo to blah
#

_usage()
{
    echo >&2 "Usage: promote [options]  __pmFoo [[pmFoo] file ...]"
    echo >&2 "       demote [options]  pmFoo [[__pmFoo] file ...]"
    echo >&2 "options:"
    echo >&2 " -d	struct name, or typedef, or #define"
    echo >&2 "		(not function name which is the default)"
    echo >&2 " -n	show me, change nothing"
    echo >&2 " -s	suggest what should be done"
    echo >&2
    echo >&2 "Default files are from recursive descent below src man qa books debian"
    exit 1
}

promote=true
case "$0"
in
    */demote)
	promote=false
	;;
esac

function=true
showme=false
suggest=false
while getopts "dns?" c
do
    case $c
    in
	d)	# not a function
		function=false
		;;
	n)	# show me
		showme=true
		;;
	s)	# suggest
		suggest=true
		;;
	?)
		_usage
		# NOTREACHED
		;;
    esac
done
shift `expr $OPTIND - 1`

if [ -z "$1" ]
then
    _usage
    # NOTREACHED
fi
from="$1"
from_pat="(^|[^a-zA-Z0-9_])$from(\$|[^a-zA-Z0-9_])"
shift
if [ $# -ge 1 ]
then
    to="$1"
    shift
else
    if $promote
    then
	to=`echo "$from" | sed -n -e 's/^__pm/pm/p'`
	if [ -z "$to" ]
	then
	    echo >&2 "Error: from=$from does not start with \"__pm\""
	    exit 1
	fi
    else
	to=`echo "$from" | sed -n -e 's/^pm/__pm/p'`
	if [ -z "$to" ]
	then
	    echo >&2 "Error: from=$from does not start with \"pm\""
	    exit 1
	fi
    fi
fi

$showme && echo >&2 "Info: promote \"$from\" -> \"$to\""

tmp=/var/tmp/$$
trap "rm -f $tmp.*; exit 0" 0 1 2 3 15
rm -f $tmp.*

if [ $# -eq 0 ]
then
    if [ ! -d .git ]
    then
	echo >&2 "Error: need to be at the base of the git tree, bozo"
	exit 1
    fi
    topdir=''
    $showme && echo >&2 "Info: topdir=$topdir"
    find src man qa books debian -type f
else
    here=`pwd`
    rm -f $tmp.tmp
    while true
    do
	if [ -d .git ]
	then
	    topdir=`pwd`/
	    break
	fi
	if [ `pwd` = "/" ]
	then
	    echo >&2 "Error: no .git between / and $here, do you know what you're doing?"
	    exit 1
	fi
	cd ..
    done
    cd $here
    $showme && echo >&2 "Info: topdir=$topdir"

    for arg
    do
	echo $arg
    done
fi >$tmp.list

cat $tmp.list \
| while read file
do
    case $file
    in
	# these ones are binary, or expected to hold the old symbol name
	# or artifacts created in the build or QA detritis
	#
	*.so.*|*/deprecated.[ch]|*/exports|${topdir}qa/src/qa_libpcp_compat.c|${topdir}qa/1166|${topdir}qa/1166.out|${topdir}src/libpcp/src/derive_parser.y|${topdir}qa/*.bad|${topdir}src/pmie/src/fun.c)
	    ;;

	*.c|*.h|*.cpp|*.cxx|*.in|*.y|*.l|*.xs|*.[1-8]|*.xml|${topdir}qa/[0-9]*|*.install)
	    if grep -E "$from_pat" $file >/dev/null
	    then
		echo >&2 "$file:"
		# TODO
		sed <$file >$tmp.tmp \
		    -e "s/\\([^a-zA-Z0-9_]\\)$from\\([^a-zA-Z0-9_]\\)/\\1$to\\2/g" \
		    -e "s/^$from\\([^a-zA-Z0-9_]\\)/$to\\1/" \
		    -e "s/\\([^a-zA-Z0-9_]\\)$from\$/\\1$to/" \
		    -e "s/^$from\$/$to/" \
		# end
		if $showme
		then
		    diff >&2 -u $file $tmp.tmp
		else
		    cp $tmp.tmp $file
		fi
	    fi
	    ;;
    esac
done

# expect #define or prototype or typdef or extern in deprecated.h
#
if [ -f ${topdir}src/include/pcp/deprecated.h ]
then
    sed -e 's/^/ /' -e 's/$/ /' -e '/^#/d' <${topdir}src/include/pcp/deprecated.h >$tmp.tmp
    if grep "[^a-zA-Z0-9_]$from[^a-zA-Z0-9_]" <$tmp.tmp >$tmp.out
    then
	:
    else
	echo "Warning: no reference to \"$from\" in deprecated.h"
	if $suggest
	then
	    echo "? * $from()		$to()"
	    echo "? #define $from $to"
	fi
    fi
    if grep "[^a-zA-Z0-9_]$to[^a-zA-Z0-9_]" <$tmp.tmp >$tmp.out
    then
	:
    else
	echo "Warning: no reference to \"$to\" in deprecated.h"
    fi
    if $showme
    then
	grep -E "[^a-zA-Z0-9_]($from|$to)[^a-zA-Z0-9_]" <$tmp.tmp >$tmp.out
	if [ -s $tmp.out ]
	then
	    echo >&2 "details from deprecated.h:"
	    cat >&2 $tmp.out
	fi
    fi
else
    echo >&2 "Warning: cannot find ${topdir}src/include/pcp/deprecated.h"
fi

# expect $to in pmapi.h
#
if [ -f ${topdir}src/include/pcp/pmapi.h ]
then
    sed -e 's/^/ /' -e 's/$/ /' -e '/^#/d' <${topdir}src/include/pcp/pmapi.h >$tmp.tmp
    if grep "[^a-zA-Z0-9_]$to[^a-zA-Z0-9_]" <$tmp.tmp >$tmp.out
    then
	:
    else
	echo "Warning: no reference to \"$to\" in pmapi.h"
    fi
else
    echo >&2 "Warning: cannot find ${topdir}src/include/pcp/pmapi.h"
fi

# promote
#	do not expect $to or $from in impl.h nor libpcp.h
# demote
#	do not expect $to or $from in pmapi.h nor impl.h nor libpcp.h
#
for inc in pmapi.h impl.h libpcp.h
do
    [ "$inc" = pmapi.h ] && $promote && continue
    if [ -f ${topdir}src/include/pcp/$inc ]
    then
	sed -e 's/^/ /' -e 's/$/ /' -e '/^#/d' <${topdir}src/include/pcp/$inc >$tmp.tmp
	if grep "[^a-zA-Z0-9_]$from[^a-zA-Z0-9_]" <$tmp.tmp >$tmp.out
	then
	    echo "Warning: reference to \"$from\" in $inc"
	fi
	if grep "[^a-zA-Z0-9_]$to[^a-zA-Z0-9_]" <$tmp.tmp >$tmp.out
	then
	    echo "Warning: reference to \"$from\" in $inc"
	fi
	if $showme
	then
	    grep -E "[^a-zA-Z0-9_]($from|$to)[^a-zA-Z0-9_]" <$tmp.tmp >$tmp.out
	    if [ -s $tmp.out ]
	    then
		echo >&2 "details from $inc:"
		cat >&2 $tmp.out
	    fi
	fi
    else
	echo >&2 "Warning: cannot find ${topdir}src/include/pcp/$inc.h"
    fi
done

if $function
then
    # expect $from function deprecated.c
    #
    if [ -f ${topdir}src/libpcp/src/deprecated.c ]
    then
	if grep "^$from *(" ${topdir}src/libpcp/src/deprecated.c >$tmp.out
	then
	    :
	else
	    echo "Warning: no reference to \"$from\" in deprecated.c"
	    if $suggest
	    then
		cat <<End-of-File
? #undef $from
? [type]
? $from([args])
? {
?     return $to([args]);
? }
End-of-File
	    fi
	fi
	if $showme
	then
	    if [ -s $tmp.out ]
	    then
		echo >&2 "declaration from deprecated.c:"
		cat >&2 $tmp.out
	    fi
	fi
    else
	echo >&2 "Warning: cannot find ${topdir}src/libpcp/src/deprecated.c"
    fi

    # expect $from and $to symbols in exports
    #
    if [ -f ${topdir}src/libpcp/src/exports ]
    then
	for func in $from $to
	do
	    if grep "^[ 	]*$func;" ${topdir}src/libpcp/src/exports >$tmp.out
	    then
		:
	    else
		echo "Warning: no reference to \"$func\" in libpcp exports"
		$suggest && echo "?    $func;"
	    fi
	done
    else
	echo >&2 "Warning: cannot find ${topdir}src/libpcp/src/exports"
    fi

    # expect man page entry for $to, none for $old
    #
    if [ -d ${topdir}man/man3 ]
    then
	rm -f $tmp.ok
	find ${topdir}man/man3* -type f \
	| while read file
	do
	    if grep "\\\\f3$to\\\\f1" <$file >/dev/null
	    then
		$showme && echo >&2 "$file: contains man entry for $to"
		echo $file >>$tmp.ok
	    fi
	    if grep "\\\\f3$from\\\\f1" <$file >/dev/null
	    then
		echo "Warning: $file: contains man entry for $from"
	    fi
	done
	if [ ! -f $tmp.ok ]
	then
	    echo "Warning: no man entry for $to"
	fi
    else
	echo >&2 "Warning: cannot find ${topdir}man/man3"
    fi

    # expect entries for $to [$tmp.ok] in debian inventories
    #
    if [ -d ${topdir}debian ]
    then
	rm -f $tmp.routine.ok $tmp.file.ok
	for file in ${topdir}debian/*.install
	do
	    if grep "/$to.3.gz" <$file >$tmp.out
	    then
		$showme && echo >&2 "$file: inventory contains $to man page"
		touch $tmp.routine.ok
		if [ -s $tmp.ok ]
		then
		    for man in `cat $tmp.ok`
		    do
			if grep "/$man.gz" <$file >$tmp.out
			then
			    $showme && echo >&2 "$file: inventory contains `echo $man | sed -e 's@.*/@@'` man file"
			    touch $tmp.file.ok
			    break
			fi
		    done
		fi
		break
	    fi
	done
	if [ ! -f $tmp.routine.ok ]
	then
	    echo "Warning: no Debian inventory entry for $to man page"
	    $suggest && echo "? usr/share/man/man3/$to.3.gz"
	fi
	if [ -s $tmp.ok ]
	then
	    if [ ! -f $tmp.file.ok ]
	    then
		echo "Warning: no Debian inventory entry for `cat $tmp.ok` man file"
		$suggest && echo "? usr/share/`cat $tmp.ok | tr '[A-Z]' '[a-z]'`.gz"
	    fi
	fi
    else
	echo >&2 "Warning: cannot find ${topdir}debian"
    fi
fi

# expect $from reference in qa_libpcp_compat.c
#
if [ -f ${topdir}qa/src/qa_libpcp_compat.c ]
then
    if grep " $from *(" ${topdir}qa/src/qa_libpcp_compat.c >$tmp.out
    then
	:
    else
	echo "Warning: no reference to \"$from\" in qa_libpcp_compat.c"
    fi
else
    echo >&2 "Warning: cannot find ${topdir}qa/src/qa_libpcp_compat.c"
fi

